package drongo.model.values
{
	import drongo.model.core.BaseValue;
	import drongo.model.core.IProperty;
	import drongo.model.core.IValue;
	import drongo.model.events.ModelEvent;

	/**
	 * 列表数据
	 */
	public class ArrayValue extends BaseValue
	{
		public function ArrayValue()
		{
			super();
			this.value=[];
		}
		
		override protected function ChackValue(value:*):void
		{
			if(value!=null){
				var isArray:Boolean=value is Array
				if(!isArray){
					throw new Error("设置的value非Array类型");
				}
			}
		}
		
		private function ChildValueChanged(e:ModelEvent):void{
			var target:IValue=e.target as IValue;
			if(this.hasEventListener(ModelEvent.CHILD_VALUE_CHANGED)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.CHILD_VALUE_CHANGED,target));
			}
		}
		
		private function ChildChildValueChanged(e:ModelEvent):void{
			var target:IValue=e.target as IValue;
			if(this.hasEventListener(ModelEvent.CHILD_VALUE_CHANGED)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.CHILD_VALUE_CHANGED,target));
			}
		}
		
		public function AddAt(index:int,value:IValue):void{
			this.list.splice(index,0,value);
			if(this.hasEventListener(ModelEvent.ADD_CHILD)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.ADD_CHILD,index));
			}
			value.addEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
			value.addEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
		}
		
		public function Remove(value:IValue):void{
			var index:int=this.list.indexOf(value);
			if(index>=0){
				this.list.splice(index,1);
			}
			if(this.hasEventListener(ModelEvent.REMOVE_CHILD)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.REMOVE_CHILD,index));
			}
			value.removeEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
			value.removeEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
		}
		
		public function RemoveAt(index:uint):IValue{
			if(index<0||index>this.list.length){
				throw new Error("要删除的索引超出数组边界！");
			}
			var result:IValue=this.list[index];
			this.list.splice(index,1);
			if(this.hasEventListener(ModelEvent.REMOVE_CHILD)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.REMOVE_CHILD,index));
			}
			result.removeEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
			result.removeEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
			return result;
		}
		
		public function Push(value:IValue):void{
			var index:uint=this.list.length;
			this.list.push(value);
			if(this.hasEventListener(ModelEvent.ADD_CHILD)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.ADD_CHILD,index));
			}
			value.addEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
			value.addEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
		}
		
		public function Unshift(value:IValue):void{
			this.list.unshift(value);
			if(this.hasEventListener(ModelEvent.ADD_CHILD)){
				this.dispatchEvent(ModelEvent.Create(ModelEvent.ADD_CHILD,0));
			}
			value.addEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
			value.addEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
		}
		
		public function Shift():IValue{
			if(this.list.length>0){
				if(this.hasEventListener(ModelEvent.REMOVE_CHILD)){
					this.dispatchEvent(ModelEvent.Create(ModelEvent.REMOVE_CHILD,0));
				}
				var result:IValue=this.list.shift();
				result.removeEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
				result.removeEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
				return result;
			}
			return null;
		}
		
		public function Pop():IValue{
			if(this.list.length>0){
				var index:Number=this.list.length-1;
				if(this.hasEventListener(ModelEvent.REMOVE_CHILD)){
					this.dispatchEvent(ModelEvent.Create(ModelEvent.REMOVE_CHILD,index));
				}
				var result:IValue=this.list.pop();
				result.removeEventListener(ModelEvent.VALUE_CHANGED,this.ChildValueChanged);
				result.removeEventListener(ModelEvent.CHILD_VALUE_CHANGED,this.ChildChildValueChanged);
				return result;
			}
			return null;
		}
		
		/**
		 * 获取子对象的索引
		 */
		public function GetChildIndex(value:IValue):int{
			return this.list.indexOf(value);
		}
		
		/**
		 * 检测如果某个属性相等则返回
		 */
		public function GetChild(v:IProperty):IValue{
			var property:IProperty;
			var item:IValue;
			var result:IValue;
			for (var index:int = 0; index < this.list.length; index++) 
			{
				item=this.list[index];
				if(item is CollectionValue){
					property=CollectionValue(item).Get(v.GetKey());
					if(property.Equality(v)){
						result=item;
					}
				}else if(item is ArrayValue){
					result=ArrayValue(item).GetChild(v);
				}else{
					if(item.Equality(v)){
						return item;
					}
				}
			}
			return result;
		}
		
		/**
		 * 通过Key和Value 获取子内容
		 */
		public function GetChildByKeyAndValue(key:String,value:*):IValue{
			var property:IProperty;
			var item:IValue;
			var result:IValue;
			for (var index:int = 0; index < this.list.length; index++) 
			{
				item=this.list[index];
				if(item is CollectionValue){
					result=CollectionValue(item).Get(key);
					if(result!=null){
						if(result.GetValue()==value){
							return item;
						}
					}
				}else if(item is ArrayValue){
					result=ArrayValue(item).GetChildByKeyAndValue(key,value);
				}else if(!(item is IProperty)){
					if(item.GetValue()==value){
						return item;
					}
				}
			}
			return null;
		}
		
		/**
		 * 是否包含该内容
		 */
		public function contain(value:IValue):Boolean{
			for each (var i:IValue in this.list) 
			{
				if(i.Equality(value)){
					return true;
				}
			}
			return false;
		}
		
		override public function Equality(value:IValue):Boolean{
			if(value is ArrayValue){
				var arrValue:ArrayValue=value as ArrayValue;
				if(this.list.length!=arrValue.length){
					return false;
				}
				var a:IValue;
				var b:IValue;
				for (var i:int = 0; i < this.length; i++) 
				{
					a=this.list[i];
					b=arrValue.GetAt(i);
					if(a.Equality(b)==false){
						return false;
					}
				}
				return true;
			}
			return false;
		}
		
		/**
		 * 获取指定索引的内容
		 */
		public function GetAt(index:Number):IValue{
			return this.list[index];
		}
		
		public function get length():uint{
			return this.list.length;
		}
		
		override public function Decode(type:uint, data:*):void
		{
			if(type==0){
				var item:*;
				var value:IValue;
				for (var i:int = 0; i < data.length; i++) 
				{
					item=data[i];
					if(item is Array){
						value=new ArrayValue();
					}else{
						//字符串
						if(item is String){
							value=new StringValue();
						}else{
							var numValue:Number=Number(item);
							//非数字
							if(isNaN(numValue)){
								value=new CollectionValue();
							}else{
								value=new NumberValue();
							}
						}	
					}
					value.Decode(type,item);
					this.Push(value);
				}
			}
		}
		
		override public function Encode(type:uint, data:*=null):*
		{
			if(type==0){
				var result:Array=[];
				var item:IValue;
				for (var i:int = 0; i < list.length; i++) 
				{
					item=list[i];
					result.push(item.Encode(type));
				}
				return result;
			}
			return null;
		}
		
		protected function get list():Array{
			return this.value as Array;
		}
	}
}